import {computed, createStore, designComponent, designPage, PropType, reactive} from "@peryl/react-compose";
import {Button, createSimpleDate, DatePicker, Icon, Input, InputGroup, InputNumber, NumberRange, PageCard, PageCardContent, PageCardTitle, Space, Tab, TabGroup, Tooltip} from "plain-design";
import {chunk} from "@peryl/utils/chunk";
import {copyToClipboard} from "@peryl/utils/copyToClipboard";
import {env} from "../../env";

const tabStore = createStore({
  initialState: undefined as undefined | string,
  getCacheConfig: () => ({
    cacheName: 'STORE_TABS',
    envName: env.envName,
  })
});

export default designPage(() => {

  const state = reactive({
    queryDateString: getPrevDateString(today.getDisplay(), 0),
    publicPrefix: '非北证非创业非科创非ST，',
  });

  return () => {
    const { publicPrefix, queryDateString } = state;
    const publicProps = { publicPrefix, queryDateString };
    return (<>
      <PageCard size="small">
        <PageCardTitle title="公共参数"/>
        <PageCardContent>
          <Space vertical>
            <InputGroup>
              <Input modelValue="查询日期：" readonly fixedWidth width="90px"/>
              <DatePicker placeholder="选择查询日期" v-model={state.queryDateString} fixedWidth width="150px"/>
              <Tooltip message="上一个交易日"><Button icon="pi-arrow-up" onClick={() => state.queryDateString = getPrevDateString(state.queryDateString, 1)}/></Tooltip>
              <Tooltip message="下一个交易日"><Button icon="pi-arrow-down" onClick={() => state.queryDateString = getNextDateString(state.queryDateString, 1)}/></Tooltip>
              <Input modelValue="通用前缀：" readonly fixedWidth width="90px"/>
              <Input placeholder="通用前缀" v-model={state.publicPrefix}/>
            </InputGroup>
          </Space>
        </PageCardContent>
      </PageCard>
      <TabGroup size="small" v-model={tabStore.value}>
        <Tab title="涨停复制" val="RaiseUpPanel"><RaiseUpPanel {...publicProps}/></Tab>
        <Tab title="内秀十字星" val="CrossStar"><CrossStar {...publicProps}/></Tab>
        <Tab title="连板查询" val="ConsecutivePanel"><ConsecutivePanel {...publicProps}/></Tab>
        <Tab title="进板查询" val="PassPanel"><PassPanel {...publicProps}/></Tab>
        <Tab title="连续小阳线" val="ContinuePositiveBar"><ContinuePositiveBar {...publicProps}/></Tab>
        {/*<Tab title="尾盘选股">涨停复制</Tab>*/}
      </TabGroup>
    </>);
  };
});

const PublicPanelPropsOption = {
  queryDateString: { type: String, required: true },
  publicPrefix: { type: String, required: true },
} as const;

/**
 * 进板查询
 * @author  韦胜健
 * @date    2025/1/19 20:41
 */
const PassPanel = designComponent({
  props: PublicPanelPropsOption,
  setup({ props }) {

    const state = reactive({
      /*总板数*/
      passCount: 10,
    });

    const passList = computed((): iStockPassMeta[] => {
      const count = state.passCount || 10;
      const ret: iStockPassMeta[] = [];
      new Array(count).fill(0).forEach((_, index) => {
        const count = index + 1;
        const name = `${count}进${count + 1}`;
        const val: iStockPassMeta['val'] = [];
        val.push(0);
        val.push(...new Array(count).fill(1));
        val.push(null);
        ret.push({ name, val });
        ret.push({ name: `${name}成功`, val: [...val.slice(0, -1), 1] });
        ret.push({ name: `${name}失败`, val: [...val.slice(0, -1), 0] });
      });
      return ret;
    });

    return () => (
      <>
        <PageCard size="small">
          <PageCardContent>
            <InputGroup>
              <Input modelValue="进板数量：" readonly fixedWidth width="100px"/>
              <InputNumber v-model={state.passCount} fixedWidth width="90px"/>
            </InputGroup>
          </PageCardContent>
        </PageCard>
        {chunk(passList.value, 3).map((list, listIndex) => (
          <PlateList
            list={list} key={listIndex}
            publicPrefix={props.publicPrefix}
            queryDateString={props.queryDateString}
          />
        ))}
      </>
    );
  }
});

/**
 * 连板查询
 * @author  韦胜健
 * @date    2025/1/19 20:41
 */
const ConsecutivePanel = designComponent({
  props: PublicPanelPropsOption,
  setup({ props }) {

    const state = reactive({ passCount: 10 });

    const consecutiveList = computed(() => {
      const ret = [] as iStockPassMeta[];
      new Array(state.passCount).fill(0).forEach((_, index) => {
        const count = index + 1;
        const name = `${count}板`;
        ret.push({ name, val: [0, ...new Array(count).fill(1)] });
      });
      return ret;
    });

    return () => (
      <>
        <PageCard size="small">
          <PageCardContent>
            <InputGroup>
              <Input modelValue="连板数量：" readonly fixedWidth width="100px"/>
              <InputNumber v-model={state.passCount} fixedWidth width="90px"/>
            </InputGroup>
          </PageCardContent>
        </PageCard>
        <PlateList
          list={consecutiveList.value}
          publicPrefix={props.publicPrefix}
          queryDateString={props.queryDateString}
        />
      </>
    );
  }
});

/**
 * 涨停复制
 * @author  韦胜健
 * @date    2025/1/19 20:42
 */
const RaiseUpPanel = designComponent({
  props: PublicPanelPropsOption,
  setup({ props }) {

    const state = reactive({
      /*最小涨幅，比如最小涨幅是1，意味着从涨停日算起不能跌超(10 - 1)%，跌超过涨停起点视为跌破支撑位，此时当前战法将不合适该股*/
      minRate: 1 as number | undefined,
      /*最大涨幅，比如最大涨幅是5，意味着从涨停日算起，跌幅不能小于(10 - 5)%*/
      maxRate: 5 as number | undefined,
      /*回调天数，一般涨停之后会有1天洗掉涨停日的套牢盘，第2天低开低走，剩下两天洗盘试盘*/
      adjustCount: 5
    });

    const queryString = computed(() => {

      const ret = [] as string[];
      ret.push(props.publicPrefix);

      let { minRate, maxRate, adjustCount } = state;

      const startDateString = getPrevDateString(props.queryDateString, (adjustCount + 1));
      ret.push(`${startDateString}涨停`);

      const subRet: string[] = [];
      subRet.push(`${startDateString}到${getPrevDateString(props.queryDateString, 1)}区间涨跌幅`);
      if (minRate != null) {
        const minRateNum = Number(minRate);
        if (!isNaN(minRateNum)) {
          subRet.push(`大于${minRateNum}%`);
        }
      }
      if (maxRate != null) {
        const maxRateNum = Number(maxRate);
        if (!isNaN(maxRateNum)) {
          subRet.push(`小于${maxRateNum}%`);
        }
      }

      if (subRet.length > 1) {
        ret.push(subRet.join(''));
      }

      return ret.join('，').replace(/[，,]+/, '，');
    });

    return () => <>
      <PageCard>
        <PageCardContent>
          <InputGroup style={{ width: '700px' }}>
            <Input modelValue="回调天数：" readonly fixedWidth width="90px"/>
            <InputNumber placeholder="回调天数" v-model={state.adjustCount} align="center"/>
            <Input modelValue="涨停日起最小涨幅：" readonly fixedWidth width="120px"/>
            <InputNumber placeholder="涨停日起最小涨幅" v-model={state.minRate} align="center"/>
            <Input modelValue="涨停日起最大涨幅：" readonly fixedWidth width="120px"/>
            <InputNumber placeholder="涨停日起最大涨幅" v-model={state.maxRate} align="center"/>
          </InputGroup>
        </PageCardContent>
        <PageCardContent>
          <Button icon="pi-copy" style={{ marginRight: '1em' }} onClick={() => {copyToClipboard(queryString.value);}}/>
          <span>{queryString.value}</span>
        </PageCardContent>
      </PageCard>
    </>;
  },
});

/**
 * 内秀十字星
 * @author  韦胜健
 * @date    2025/1/19 21:27
 */
const CrossStar = designComponent({
  props: PublicPanelPropsOption,
  setup({ props }) {

    const state = reactive({
      min: 4,
      max: -8
    });

    const queryString = computed(() => {

      const ret = [] as string[];
      // ret.push(props.publicPrefix);

      const startDateString = getPrevDateString(props.queryDateString, 0);
      const prevDateString = getPrevDateString(props.queryDateString, 1);

      ret.push(`${startDateString}开盘涨跌幅<=-1`);
      ret.push(`${startDateString}涨跌幅>=-8`);
      ret.push(`${startDateString}振幅<=6`);
      ret.push(`${prevDateString}涨跌幅>4`);

      ret.push(`${startDateString}最高价<${prevDateString}最高价`);
      ret.push(`${startDateString}最低价>${prevDateString}最低价`);

      // ret.push(`${prevDateString}涨跌幅>${state.min}`);
      // ret.push(`${startDateString}涨跌幅>${state.max}`);
      ret.push(`${startDateString}量比<1`);

      ret.push(`${getPrevDateString(props.queryDateString, 3)}至${startDateString}区间涨停天数>=1`);

      return ret.join('，').replace(/[，,]+/, '，');

    });

    return () => (
      <PageCard>
        <PageCardContent>
          <InputGroup style={{ width: '700px' }}>
            <Input modelValue="前日最小涨幅：" readonly fixedWidth width="100px"/>
            <InputNumber placeholder="前日最小涨幅" v-model={state.min} align="center"/>
            <Input modelValue="当日最大跌幅：" readonly fixedWidth width="100px"/>
            <InputNumber placeholder="当日最大跌幅" v-model={state.max} align="center"/>
          </InputGroup>
        </PageCardContent>
        <PageCardContent>
          <Button icon="pi-copy" style={{ marginRight: '1em' }} onClick={() => {copyToClipboard(queryString.value);}}/>
          <span>{queryString.value}</span>
        </PageCardContent>
      </PageCard>
    );
  },
});

/**
 * 连续小阳线
 * @author  韦胜健
 * @date    2025/2/7 21:31
 */
const ContinuePositiveBar = designComponent({
  props: PublicPanelPropsOption,
  setup({ props, }) {

    const state = reactive({
      barNum: 3,
      min: 0,
      max: 2,
    });

    const queryString = computed(() => {
      let barNum = 0;
      const ret: string[] = [];
      while (barNum < state.barNum) {
        const dateString = getPrevDateString(props.queryDateString, barNum);
        barNum++;
        ret.unshift(`${dateString}涨跌幅>=0并且<=2`);
      }
      return ret.join(',');
    });

    return () => (
      <PageCard>
        <PageCardContent>
          <InputGroup style={{ width: '700px' }}>
            <Input modelValue="阳线数量：" readonly fixedWidth width="100px"/>
            <InputNumber placeholder="阳线数量" v-model={state.barNum} align="center"/>
            <Input modelValue="阳线最小涨幅：" readonly fixedWidth width="100px"/>
            <InputNumber placeholder="阳线最小涨幅" v-model={state.min} align="center"/>
            <Input modelValue="阳线最大涨幅：" readonly fixedWidth width="100px"/>
            <InputNumber placeholder="阳线最大涨幅" v-model={state.max} align="center"/>
          </InputGroup>
        </PageCardContent>
        <PageCardContent>
          <Button icon="pi-copy" style={{ marginRight: '1em' }} onClick={() => {copyToClipboard(queryString.value);}}/>
          <span>{queryString.value}</span>
        </PageCardContent>
      </PageCard>
    );
  },
});

/*---------------------------------------下边都是工具函数或者组件-------------------------------------------*/

const today = DatePicker.plainDate.today();

const getLastWorkingDate = (_date: Date): Date => {
  const date = new Date(_date.getTime());
  const day = date.getDay();
  if (day == 0) {date.setMonth(date.getMonth(), date.getDate() - 2);}
  if (day == 6) {date.setMonth(date.getMonth(), date.getDate() - 1);}
  return date;
};

const getPrevDateString = (queryDateString: string, prevCount: number): string => {
  let selectWorkingDate = getLastWorkingDate(today.useDisplay(queryDateString).getDate());
  while (prevCount > 0) {
    selectWorkingDate.setMonth(selectWorkingDate.getMonth(), selectWorkingDate.getDate() - 1);
    selectWorkingDate = getLastWorkingDate(selectWorkingDate);
    prevCount--;
  }
  return createSimpleDate(selectWorkingDate)["YYYY-MM-DD"];
};

const getNextWorkingDate = (_date: Date): Date => {
  const date = new Date(_date.getTime());
  const day = date.getDay();
  if (day == 0) {date.setMonth(date.getMonth(), date.getDate() + 1);}
  if (day == 6) {date.setMonth(date.getMonth(), date.getDate() + 2);}
  return date;
};

const getNextDateString = (queryDateString: string, nextCount: number): string => {
  let selectWorkingDate = getNextWorkingDate(today.useDisplay(queryDateString).getDate());
  while (nextCount > 0) {
    selectWorkingDate.setMonth(selectWorkingDate.getMonth(), selectWorkingDate.getDate() + 1);
    selectWorkingDate = getNextWorkingDate(selectWorkingDate);
    nextCount--;
  }
  return createSimpleDate(selectWorkingDate)["YYYY-MM-DD"];
};

const getQueryPassString = (passVal: iStockPassMeta['val'], queryDateString: string, publicPrefix: string): string => {
  let str = publicPrefix;
  if (!(str.endsWith(',') || str.endsWith('，'))) {
    str = str + '，';
  }

  if (passVal.length <= 3) {
    str = str + '市值小于100亿，';
  }

  const list = [...passVal].reverse();
  list.forEach((flag, index) => {
    const dateString = getPrevDateString(queryDateString, index);
    if (flag == null) {
      // str = str + `${dateString}涨幅，`;
    } else {
      str = str + `${dateString}${flag == 1 ? '涨幅大于9.8%' : '涨跌幅<9%'}，`;
    }
  });

  /*if (list[0] == null) {
    str = str + `按照${getPrevDateString(queryDateString, 0)}涨跌幅降序排序，`;
  } else if (list[0] == 1) {
    str = str + `按照${getPrevDateString(queryDateString, 0)}振幅升序排序，`;
  } else if (list[0] == 0) {
    str = str + `按照${getPrevDateString(queryDateString, 0)}涨跌幅降序排序，`;
  }*/
  str = str + `按照热度排名升序，`;

  return str;
};

const PlateList = designComponent({
  props: {
    list: { type: Array as PropType<iStockPassMeta[]>, required: true },
    publicPrefix: { type: String, required: true },
    queryDateString: { type: String, required: true },
  },
  setup({ props }) {
    return () => (
      <PageCard size="small">
        {props.list.map((item, index) => (
          <PageCardContent key={index}>
            {(() => {
              const queryPassString = getQueryPassString(item.val, props.queryDateString, props.publicPrefix);
              return <>
                <Button icon="pi-copy" style={{ marginRight: '1em' }} onClick={() => {copyToClipboard(queryPassString);}}/>
                <span>{item.name}：{queryPassString}</span>
              </>;
            })()}
          </PageCardContent>
        ))}
      </PageCard>
    );
  },
});

interface iStockPassMeta {
  name: string,
  val: (1 | 0 | null)[]
}
